/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.atomojo.app.client;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Map;
import java.util.TreeMap;
import org.infoset.xml.DocumentLoader;
import org.infoset.xml.Element;
import org.infoset.xml.Item;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.Location;
import org.infoset.xml.Name;
import org.infoset.xml.Named;
import org.infoset.xml.XMLException;
import org.infoset.xml.sax.SAXDocumentLoader;

/**
 *
 * @author alex
 */
public class Ontology {

   static URI ATOMOJO_O = URI.create("http://www.atomojo.org/O");
   static URI NAMESPACE = URI.create("http://www.atomojo.org/Vocabulary/Ontology/2008/1/0");
   static Name ONTOLOGY = Name.create(NAMESPACE,"ontology");
   static Name CATEGORY = Name.create("{http://www.w3.org/2005/Atom}category");
   
   static Ontology theInstance;

   static {
      theInstance = new Ontology();
      try {
         theInstance.load(Ontology.class.getResource("atomojo.org.xml"));
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
   
   static class TermNode {
      Term term;
      URI uri;
      TermNode parent;
      Map<String,TermNode> children;
      TermNode(Term term,TermNode parent,String separator) {
         this.term = term;
         this.parent = parent;
         this.uri = URI.create(term.getURI().toString()+separator);
         this.children = new TreeMap<String,TermNode>();
      }
   }

   Map<URI,TermNode> universe;
   public Ontology() {
      this.universe = new TreeMap<URI,TermNode>();
   }

   public static Ontology getDefaultInstance() {
      return theInstance;
   }

   public void load(URL url) 
      throws IOException,XMLException
   {
      DocumentLoader loader = new SAXDocumentLoader();
      try {
         loader.generate(url.toURI(), new ItemDestination() {
            String separator = "/";
            TermNode current = null;
            public void send(Item item) 
               throws XMLException
            {
               switch (item.getType()) {
                  case ElementItem: {
                     Element e = (Element)item;
                     Name name = e.getName();
                     if (name.equals(CATEGORY)) {
                        String termName = e.getAttributeValue("term");
                        if (termName==null) {
                           throw new XMLException("The term element is missing the 'term' attribute.",(Location)e);
                        }
                        termName = termName.trim();
                        if (termName.length()==0) {
                           throw new XMLException("The term element's 'term' attribute is empty.",(Location)e);
                        }
                        Term term = Term.derive(current==null ? null : current.uri, e);
                        current = new TermNode(term,current,separator);
                        current.parent.children.put(term.getName(),current);
                        universe.put(term.getURI(), current);
                     } else if (name.equals(ONTOLOGY)) {
                        String tname = e.getAttributeValue("scheme");
                        if (tname==null) {
                           throw new XMLException("The ontology element is missing the 'scheme' attribute.",(Location)e);
                        }
                        separator = e.getAttributeValue("separator");
                        if (separator==null) {
                           separator = "/";
                        }
                        tname = tname.trim();
                        if (tname.length()==0) {
                           throw new XMLException("The ontology element's scheme attribute is empty.",(Location)e);
                        }
                        URI id = URI.create(tname);
                        Term term = new Term(id);
                        current = new TermNode(term,null,separator);
                        universe.put(term.getURI(), current);
                     }
                  }
                     break;
                  case ElementEndItem:
                  {
                     Name name = ((Named)item).getName();
                     if (name.equals(CATEGORY) || name.equals(ONTOLOGY)) {
                        if (current!=null) {
                           current = current.parent;
                        }
                     }
                  }
                     break;
               }
            }
         });
      } catch (URISyntaxException ex) {
         throw new XMLException("Cannot convert URL to URI.",ex);
      }
   }
   
   void add(Term t) {
      universe.put(t.getURI(),new TermNode(t,null,"/"));
   }
   
   public Term get(URI uri) {
      return universe.get(uri).term;
   }
   
   public Term find(URI base,String path) {
      TermNode current = universe.get(base);
      if (current==null) {
         return null;
      }
      String [] segments = path.split("/");
      for (int i=0; current!=null && i<segments.length; i++) {
         current = current.children.get(segments[i]);
      }
      return current==null ? null : current.term;
   }
   
}
